#include <iostream>
#include "../logs/log.h"

//扩展的日志系统落地方式:
//以时间段滚动的落地方式
    /*
        以时间来滚动的落地方式 ---- 实际上是以一个时间段进行滚动的
        实现思想:以当前系统时间, 取模时间段大小, 可以得到当前时间段是第几个时间段,
        每次以当前系统时间取模, 判断与当前文件的时间段是否一致, 不一致带边不是同一个时间段;
    */
enum class TimeGap
{
    GAP_SECOND, // 1s为一个时间段
    GAP_MINUTE, // 1分钟为一个时间段
    GAP_HOUR,   // 1小时为一个时间段
    GAP_DAY     // 1天为一个时间段
};
class RollByFileTimeLogSink : public Log::LogSink
{
public:
    RollByFileTimeLogSink(const std::string& baseFName, TimeGap gapType)
    :_baseFName(baseFName)
    {
        switch(gapType)
        {
            case TimeGap::GAP_SECOND:
                _gapSize = 1;
                break;
            case TimeGap::GAP_MINUTE:
                _gapSize = 60;
                break;
            case TimeGap::GAP_HOUR:
                _gapSize = 3600;
                break;
            case TimeGap::GAP_DAY:
                _gapSize = 24 * 3600;
                break;
            default:
                break;
        }
        _currGap = Log::util::Date::now() / _gapSize;    //获取创建文件的时间段
        std::string pathName = GenerateFileExtension();
        // 创建文件所在的目录
        Log::util::file::CreateDir(Log::util::file::Path(pathName));
        //创建并打开文件
        _ofs.open(pathName, std::ios::binary | std::ios::app);
        if(_ofs.is_open() == false)
        {
            std::cout << "文件打开失败!" << std::endl;
            abort();
        }
    }

    void Log(const char* data, size_t len) override
    {
        time_t nowTime = Log::util::Date::now();
        size_t nowTimeGap = nowTime / _gapSize;
        if (nowTimeGap != _currGap)
        {
            // 当前时间戳得到的时间段和创建文件时的时间段不相等,就说明不在同一个时间段内需要创建新的文件;
            // 需要创建新的文件,先关闭旧的文件流
            _ofs.close();

            // 生成文件扩展名
            std::string pathName = GenerateFileExtension();
            // 打开文件
            _ofs.open(pathName, std::ios::binary | std::ios::app);
            if (_ofs.is_open() == false)
            {
                std::cout << "文件打开失败!" << std::endl;
                abort();
            }
            _currGap = Log::util::Date::now() / _gapSize;
        }
        _ofs.write(data, len);
        if (_ofs.good() == false)
        {
            // 判断是否写入成功
            std::cout << "文件写入失败!" << std::endl;
            abort();
        }
    }
    ~RollByFileTimeLogSink()
    {
        _ofs.close();
    }

private:
    // 生成文件扩展名
    std::string GenerateFileExtension()
    {
        // 获取系统时间, 以时间来构造文件的扩展名
        time_t tm = Log::util::Date::now();
        struct tm currtime;
        localtime_r(&tm, &currtime);
        std::stringstream fileExtensionName;
        fileExtensionName << _baseFName;
        fileExtensionName << currtime.tm_year + 1900;
        fileExtensionName << currtime.tm_mon + 1;
        fileExtensionName << currtime.tm_mday;
        fileExtensionName << currtime.tm_hour;
        fileExtensionName << currtime.tm_min;
        fileExtensionName << currtime.tm_sec;
        fileExtensionName << ".log";
        return fileExtensionName.str();
    }

private:
    std::string _baseFName; //基础文件名,采用基础文件名加扩展文件名的方式, 扩展文件名使用时间来命名
    std::ofstream _ofs;
    size_t _currGap; //当前创建文件的时间段
    size_t _gapSize;    //时间段的大小
};


int main()
{
    std::unique_ptr<Log::LoggerBuilder> builder(new Log::GlobalLoggerBuilder()); 
    builder->buildLoggerType(Log::LoggerType::LOGGER_SYNC);    //日志器类型的选择: 同步日志器/异步日志器
    const std::string loggerName = "syncLogger-1";
    //builder->buildEnableDynamicAsync(Log::BufferType::DYNAMICGROW);   //日志器的缓冲区类型: 动态增长类型的缓冲区
    builder->buildLoggerName(loggerName);
    builder->buildLimitLevel(Log::LogLevel::value::INFO);
    builder->buildFormatter("[%d{%Y-%m-%d %H:%M:%S}][%t][%f:%l][%p]%T[%c]%T%m%n");
    builder->buildSinks<RollByFileTimeLogSink>("./logfile/rolltime-", TimeGap::GAP_SECOND);
    builder->build();
    Log::Logger::ptr logger = Log::getLogger(loggerName);
    size_t cur = Log::util::Date::now();
    while(Log::util::Date::now() < cur + 5)
    {
        logger->FATAL("这是一条日志信息...");
    }
    return 0;
}